//    Copyright (C) 2013  <lugocreation@gmail.com>
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
package org.jpgolay.me.preparation;

import java.awt.event.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.math.BigDecimal;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
import org.jpgolay.gui.date.DateComboBox;
import org.jpgolay.gui.fixed.*;
import org.jpgolay.me.batch.Batch;
import org.jpgolay.me.item.*;
import org.jpgolay.me.order.OrderRow;
import org.jpgolay.me.persistence.ObjectCRUD;
import org.jpgolay.me.stock.log.LogStock;
import org.jpgolay.me.util.*;

// Referenced classes of package org.jpgolay.me.preparation:
//            PreparationBatchGUI
public class PreparationController {

    private class MouseClickList extends MouseAdapter {

        public void mouseClicked(MouseEvent e) {
            actionAddressView();
        }

        MouseClickList() {
        }
    }

    public PreparationController(SearchBox preparationSearch, TableViewer preparationTable, PreparationBatchGUI preparationBatchGui, Parameter param) {
        this.preparationSearch = null;
        this.preparationTable = null;
        preparationSearchGui = null;
        this.preparationBatchGui = null;
        zero = new BigDecimal("0.00");
        dateComboBox = null;
        write = false;
        this.preparationSearch = preparationSearch;
        this.preparationTable = preparationTable;
        this.preparationBatchGui = preparationBatchGui;
        this.param = param;
        desktop = param.getDesktop();
        changes = new PropertyChangeSupport(this);
        itemCrud = new ItemCRUD();
        crud = new ObjectCRUD();
        initLaw();
        initSearch();
        initItemTable();
        initBatchPanel();
    }

    private void initLaw() {
        if (param.getAccessLaw().length() >= 27 && param.getAccessLaw().charAt(27) == '1') {
            write = true;
        }
    }

    private void initSearch() {
        preparationSearch.setList(new String[]{
                    "R\351f\351rence", "D\351signation", "Famille", "Fournisseur"
                });
        preparationSearch.setVal("");
        preparationSearch.setAdvanceSearch(getPreparationSearchGUI());
        preparationSearch.getButtonRight().addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                actionSearch();
            }
        });
        preparationSearch.getTextField().addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                actionSearch();
            }
        });
    }

    private void initItemTable() {
        preparationTable.setTypes(new Class[]{
                    java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class
                });
        preparationTable.setLastColumnNotEditable(0);
        preparationTable.setCellEditable(false);
        preparationTable.setAlternateColor(MEUtility.ITEM_LINE);
        preparationTable.setColumnNames(new String[]{
                    "REFERENCE", "DESIGNATION", "FAMILLE", "FOURNISSEUR"
                });
        preparationTable.setPreferredColumnSize(new int[]{
                    50, 50, 40, 40
                });
        actionSearch();
    }

    private void initBatchPanel() {
        preparationBatchGui.cleanLabel();
        preparationBatchGui.getSaveButton().setEnabled(false);
        preparationBatchGui.getSaveButton().addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                actionSaveOrderRow();
            }
        });
        preparationBatchGui.getTableViewerPanel().setTypes(new Class[]{
                    java.lang.Integer.class, java.lang.Integer.class, java.lang.String.class, java.math.BigDecimal.class, java.math.BigDecimal.class
                });
        preparationBatchGui.getTableViewerPanel().setLastColumnNotEditable(3);
        preparationBatchGui.getTableViewerPanel().setCellEditable(write);
        preparationBatchGui.getTableViewerPanel().setAlternateColor(MEUtility.BATCH_LINE);
        preparationBatchGui.getTableViewerPanel().setColumnNames(new String[]{
                    "", "Ag", "N\260 LOT", "DISPO", "QUANTITE"
                });
        preparationBatchGui.getTableViewerPanel().setPreferredColumnSize(new int[]{
                    5, 30, 120, 70, 70
                });
        preparationBatchGui.getTableViewerPanel().setData(getDataEmpty());
    }

    private Object[][] getDataEmpty() {
        Object data[][] = new Object[5][5];
        for (int i = 0; i < data.length; i++) {
            data[i][0] = null;
            data[i][1] = null;
            data[i][2] = null;
            data[i][3] = null;
            data[i][4] = null;
        }

        return data;
    }

    private ItemAdvanceSearchGUI getPreparationSearchGUI() {
        if (preparationSearchGui == null) {
            preparationSearchGui = new ItemAdvanceSearchGUI();
            preparationSearchGui.getItemViewerPanel().clean();
            preparationSearchGui.getItemViewerPanel().setReferenceLabel("Aucune donn\351es");
        }
        return preparationSearchGui;
    }

    private void actionSearch() {
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT ref_code_barre, designation, familles_articles_id, fournisseurs_id FROM articles");
        switch (preparationSearch.getSelectedIndex()) {
            case 0: // '\0'
                if (preparationSearch.getVal().equals("")) {
                    sql.append(" ORDER BY ref_code_barre");
                } else {
                    sql.append(" WHERE ref_code_barre LIKE '");
                    sql.append(preparationSearch.getVal());
                    sql.append("%' ORDER BY ref_code_barre");
                }
                break;

            case 1: // '\001'
                if (preparationSearch.getVal().equals("")) {
                    sql.append(" ORDER BY designation");
                } else {
                    sql.append(" WHERE designation LIKE '");
                    sql.append(preparationSearch.getVal());
                    sql.append("%' ORDER BY designation");
                }
                break;

            case 2: // '\002'
                if (preparationSearch.getVal().equals("")) {
                    sql.append(" ORDER BY familles_articles_id");
                } else {
                    sql.append(" WHERE familles_articles_id LIKE '");
                    sql.append(preparationSearch.getVal());
                    sql.append("%' ORDER BY familles_articles_id");
                }
                break;

            case 3: // '\003'
                if (preparationSearch.getVal().equals("")) {
                    sql.append(" ORDER BY fournisseurs_id");
                } else {
                    sql.append(" WHERE fournisseurs_id LIKE '");
                    sql.append(preparationSearch.getVal());
                    sql.append("%' ORDER BY fournisseurs_id");
                }
                break;

            default:
                if (preparationSearch.getVal().equals("")) {
                    sql.append(" ORDER BY ref_code_barre");
                } else {
                    sql.append(" WHERE ref_code_barre LIKE '");
                    sql.append(preparationSearch.getVal());
                    sql.append("%' ORDER BY ref_code_barre");
                }
                break;
        }
        Object data[][] = itemCrud.getDataList(sql.toString());
        if (data != null) {
            preparationTable.setData(data);
            preparationTable.getTable().addMouseListener(new MouseClickList());
            preparationSearch.setVal("");
            if (data.length == 1) {
                String old = barrecode;
                barrecode = (String) data[0][0];
            }
        } else {
            data = (new Object[][]{
                        new Object[4], new Object[4]
                    });
            preparationTable.setData(data);
            JOptionPane.showMessageDialog(null, "Aucune donn\351es de correspondent \340 votre recherche !");
        }
    }

    private void actionAddressView() {
        Item item = itemCrud.getItemByPK((String) preparationTable.getTable().getValueAt(preparationTable.getTable().getSelectedRow(), 0));
        if (item != null) {
            getPreparationSearchGUI().getItemViewerPanel().setReferenceLabel("R\351f. : " + item.getId());
            getPreparationSearchGUI().getItemViewerPanel().setTaxLabel("Tva : " + item.getTvaId().toString());
            getPreparationSearchGUI().getItemViewerPanel().setDesignationLabel(item.getDesignation());
            getPreparationSearchGUI().getItemViewerPanel().setFamilyLabel("Famille : " + item.getFamillesArticlesId());
            getPreparationSearchGUI().getItemViewerPanel().setNotesLabel(item.getCommentaire());
            getPreparationSearchGUI().getItemViewerPanel().setSiteLabel("Stock : " + item.getEmplacement());
            getPreparationSearchGUI().getItemViewerPanel().setWebLabel("Web : " + item.getWeb());
            getPreparationSearchGUI().getItemViewerPanel().setBuyDateLabel("Date achat : " + item.getDate2());
            getPreparationSearchGUI().getItemViewerPanel().setSupplierLabel("Fournis. : " + item.getFournisseurId());
            getPreparationSearchGUI().getItemViewerPanel().setSpecialOfferLabel("Promo. : " + item.getPromotion().setScale(param.getMinimumDecimalNumber().intValue(), param.getRoundType().intValue()) + "%");
            getPreparationSearchGUI().getItemViewerPanel().setWeightPriceLabel("Prix pond\351r\351 : " + item.getPrixAchatPondere().setScale(param.getMinimumDecimalNumber().intValue(), param.getRoundType().intValue()));
            getPreparationSearchGUI().getItemViewerPanel().setMarginLabel(calculateMargin(item.getPriceList1(), item.getPrixRevient()));
            getPreparationSearchGUI().getItemViewerPanel().setCostLabel("Prix revient : " + item.getPrixRevient().setScale(param.getMinimumDecimalNumber().intValue(), param.getRoundType().intValue()));
            getPreparationSearchGUI().getItemViewerPanel().setDateLabel("Date vente : " + item.getDate());
            getPreparationSearchGUI().getItemViewerPanel().setSalePriceLabel("PRIX VENTE : " + item.getPriceList1().setScale(param.getMinimumDecimalNumber().intValue(), param.getRoundType().intValue()));
        }
    }

    private void actionSearchBatch(String itemId) {
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT id,agency_id,item_batch,(stock_quantity - delta_inventory) as dispo FROM batch WHERE item_id='" + itemId + "' AND stock_quantity != 0");
        Object data[][] = itemCrud.getDataList(sql.toString());
        if (data != null) {
            Object dataShow[][] = new Object[data.length][5];
            for (int i = 0; i < data.length; i++) {
                dataShow[i][0] = new Integer((String) data[i][0]);
                dataShow[i][1] = new Integer((String) data[i][1]);
                dataShow[i][2] = data[i][2];
                dataShow[i][3] = (new BigDecimal((String) data[i][3])).setScale(param.getMinimumDecimalNumber().intValue(), param.getRoundType().intValue());
                dataShow[i][4] = new BigDecimal("0.00");
                preparationBatchGui.getTableViewerPanel().setData(dataShow);
                preparationBatchGui.getTableViewerPanel().getTableModel().addTableModelListener(new TableModelListener() {
                    public void tableChanged(TableModelEvent e) {
                        actionUpdateTotal(e.getFirstRow());
                    }
                });
            }

        } else {
            preparationBatchGui.getTableViewerPanel().setData(getDataEmpty());
            JOptionPane.showMessageDialog(null, "Aucun lot disponible pour l'article : " + itemId);
        }
    }

    private void actionUpdateTotal(int row) {
        BigDecimal total = new BigDecimal("0.00");
        Object data[][] = preparationBatchGui.getTableViewerPanel().getData();
        for (int i = 0; i < data.length; i++) {
            if (((BigDecimal) data[i][4]).compareTo((BigDecimal) data[i][3]) == 1) {
                JOptionPane.showMessageDialog(null, "La quantit\351 demand\351e d\351passe la quantit\351 disponible sur ce lot !");
                return;
            }
            total = total.add((BigDecimal) data[i][4]);
        }

        preparationBatchGui.setTotalVal(total.toPlainString());
        if (total.compareTo(zero) == 0) {
            preparationBatchGui.getSaveButton().setEnabled(false);
        } else {
            preparationBatchGui.getSaveButton().setEnabled(true);
        }
    }

    private void actionSaveOrderRow() {
        if (orderRow.getQuantite().compareTo(new BigDecimal(preparationBatchGui.getTotalVal())) == 0) {
            save();
        } else {
            int reponse = JOptionPane.showConfirmDialog(null, "La quantit\351 ne correspond pas \340 la ligne s\351l\351ctionn\351e !\nConfirmez vous cette modification ?", "Confirmation", 1, 2, null);
            switch (reponse) {
                case 0: // '\0'
                    save();
                    break;
            }
        }
    }

    private void save() {
        Object data[][] = preparationBatchGui.getTableViewerPanel().getData();
        listOrderRow = new ArrayList();
        for (int i = 0; i < data.length; i++) {
            BigDecimal batchQuantity = (BigDecimal) data[i][4];
            if (batchQuantity.compareTo(zero) != 0) {
                OrderRow or = new OrderRow();
                or.setArticleId(orderRow.getArticleId());
                or.setDesignation(orderRow.getDesignation());
                or.setFactureId(orderRow.getFactureId());
                if (listOrderRow.size() == 0) {
                    or.setId(orderRow.getId());
                    or.setLine(orderRow.getLine());
                }
                or.setPrixUnitaire(orderRow.getPrixUnitaire());
                or.setPrixVente(orderRow.getPrixVente());
                or.setQuantite(orderRow.getQuantite());
                or.setReliquatId(orderRow.getReliquatId());
                or.setRemise(orderRow.getRemise());
                or.setStatus(orderRow.getStatus());
                or.setTotalHt(orderRow.getTotalHt());
                or.setTvaId(orderRow.getTvaId());
                or.setUpdateLastTime(orderRow.getUpdateLastTime());
                or.setUserId(orderRow.getUserId());
                or.setVenteId(orderRow.getVenteId());
                or.setBatchId((Integer) data[i][0]);
                or.setLotId((String) data[i][2]);
                or.setStatus(batchQuantity);
                if (batchQuantity.compareTo(orderRow.getQuantite()) != 0) {
                    or.setQuantite(batchQuantity);
                }
                updateBatch((Integer) data[i][0], batchQuantity);
                listOrderRow.add(or);
            }
        }

        preparationBatchGui.cleanLabel();
        preparationBatchGui.getTableViewerPanel().setData(getDataEmpty());
        preparationBatchGui.getSaveButton().setEnabled(false);
        changes.firePropertyChange("updatePiece", "old", "new");
    }

    private void updateBatch(Integer pk, BigDecimal quantity) {
        Batch batch = (Batch) crud.read(pk, 31);
        if (batch != null) {
            batch.setStockQuantity(batch.getStockQuantity().subtract(quantity));
            batch.setUserId(param.getUserId());
            crud.update(batch, 31);
            Integer id = (Integer) crud.create(32, null);
            LogStock logStock = (LogStock) crud.read(id, 32);
            if (logStock != null) {
                logStock.setBatchId(batch.getId());
                logStock.setDate((new MEDate()).getPlain());
                logStock.setDe("STOCK Agence " + batch.getAgencyId().toString());
                logStock.setItemId(batch.getItemId());
                logStock.setNotes("Pr\351paration (n\260 lot : " + batch.getItemBatch() + ")");
                logStock.setOperation("SORTIE");
                logStock.setQuantity(quantity);
                logStock.setUserId(param.getUserId());
                logStock.setVers("C/BL " + orderRow.getVenteId());
                crud.update(logStock, 32);
            }
        }
    }

    private String calculateMargin(BigDecimal salesPrice, BigDecimal cost) {
        try {
            BigDecimal r = salesPrice.subtract(cost).divide(salesPrice.movePointLeft(2), 2, 4);
            return "Marge : " + r.toPlainString() + "%";
        } catch (RuntimeException e) {
            return "Marge : ";
        }
    }

    public void addPropertyChangeListener(PropertyChangeListener l) {
        changes.addPropertyChangeListener(l);
    }

    public void removePropertyChangeListener(PropertyChangeListener l) {
        changes.removePropertyChangeListener(l);
    }

    public void setBatchChoice(OrderRow orderRow, String itemId) {
        this.orderRow = orderRow;
        if (orderRow == null) {
            JOptionPane.showMessageDialog(null, "S\351l\351ctionner une ligne !");
            return;
        }
        if (orderRow.getQuantite().compareTo(orderRow.getStatus()) == 0) {
            JOptionPane.showMessageDialog(null, "Cette ligne a d\351j\340 \351t\351 trait\351e !");
            return;
        }
        Item it = (Item) crud.read(itemId, 11);
        if (it != null) {
            if (it.getId().equals(orderRow.getArticleId())) {
                preparationBatchGui.setSelectedRow(orderRow.getArticleId(), orderRow.getDesignation(), "(" + orderRow.getVenteId().toString() + ")", orderRow.getQuantite().setScale(2, 4).toPlainString());
                actionSearchBatch(itemId);
            } else {
                JOptionPane.showMessageDialog(null, "L'article s\351l\351ctionn\351 (" + it.getId() + ")\nne correspond pas a celui de la ligne trait\351e (" + orderRow.getArticleId() + ") !");
            }
        } else {
            JOptionPane.showMessageDialog(null, "L'article s\351l\351ctionn\351 n'\351xiste plus !\n(v\351rifier qu'il n'a pas \351t\351 suprimer entre temps)");
        }
    }

    public ArrayList getListOrderRow() {
        return listOrderRow;
    }

    public void setListOrderRow(ArrayList listOrderRow) {
        this.listOrderRow = listOrderRow;
    }

    public String getPreparedPieceId() {
        return orderRow.getVenteId();
    }
    private SearchBox preparationSearch;
    private TableViewer preparationTable;
    private ItemAdvanceSearchGUI preparationSearchGui;
    private PreparationBatchGUI preparationBatchGui;
    private ItemCRUD itemCrud;
    private ObjectCRUD crud;
    private JDesktopPane desktop;
    private String barrecode;
    private PropertyChangeSupport changes;
    private Parameter param;
    private OrderRow orderRow;
    private BigDecimal zero;
    private ArrayList listOrderRow;
    private DateComboBox dateComboBox;
    private boolean write;
}
